﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Windows.Forms.DataVisualization.Charting;

namespace EasyTrader.Signal
{
    using PriceWaveList = List<EasyTrader.Wave.PriceWave>;
    public class SubjectSignalManager : EasyTrader.Signal.SignalManager
    {
        public SubjectSignalManager()
            : base()
        {
            ;
        }

        private int m_CallPutInvDiv = 0;
        public int CallPutInvDiv
        {
            get { return m_CallPutInvDiv; }
            set { m_CallPutInvDiv = value; }
        }
        private System.Windows.Forms.DataVisualization.Charting.Chart m_ChartCtrl = null;

        public void InitChartCtrl()
        {
            m_ChartCtrl = new System.Windows.Forms.DataVisualization.Charting.Chart();
            System.Windows.Forms.DataVisualization.Charting.ChartArea priceArea = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
            System.Windows.Forms.DataVisualization.Charting.Legend mainLegend = new System.Windows.Forms.DataVisualization.Charting.Legend();
            priceArea.Name = "Price";
            this.m_ChartCtrl.ChartAreas.Add(priceArea);
            mainLegend.BackColor = System.Drawing.Color.Transparent;
            mainLegend.DockedToChartArea = "Price";
            mainLegend.Name = "Legend1";
            System.Windows.Forms.DataVisualization.Charting.Series seriesBuy = new System.Windows.Forms.DataVisualization.Charting.Series();
            System.Windows.Forms.DataVisualization.Charting.Series seriesSell = new System.Windows.Forms.DataVisualization.Charting.Series();
            System.Windows.Forms.DataVisualization.Charting.Series seriesAveBuy = new System.Windows.Forms.DataVisualization.Charting.Series();
            System.Windows.Forms.DataVisualization.Charting.Series seriesAveSell = new System.Windows.Forms.DataVisualization.Charting.Series();

            //seriesRange.BorderColor = System.Drawing.Color.Black;
            seriesBuy.ChartArea = "Price";
            seriesBuy.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
            //seriesRange.Color = System.Drawing.Color.LightGreen;
            seriesBuy.Legend = "Legend1";
            seriesBuy.Name = "Call";

            seriesSell.ChartArea = "Price";
            seriesSell.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
            //seriesPrice.Color = System.Drawing.Color.Blue;
            seriesSell.Legend = "Legend1";
            seriesSell.Name = "Put";

            seriesAveBuy.ChartArea = "Price";
            seriesAveBuy.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
            //seriesPrice.Color = System.Drawing.Color.Blue;
            seriesAveBuy.Legend = "Legend1";
            seriesAveBuy.Name = "AveCall";

            seriesAveSell.ChartArea = "Price";
            seriesAveSell.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
            //seriesPrice.Color = System.Drawing.Color.Blue;
            seriesAveSell.Legend = "Legend1";
            seriesAveSell.Name = "AvePut";

            this.m_ChartCtrl.Series.Add(seriesBuy);
            this.m_ChartCtrl.Series.Add(seriesSell);
            this.m_ChartCtrl.Series.Add(seriesAveBuy);
            this.m_ChartCtrl.Series.Add(seriesAveSell);
            this.m_ChartCtrl.Size = new System.Drawing.Size(1, 1);
        }

        public void SetChartData(EasyTrader.ETDataSet a_DataSet, int a_AveRange)
        {
            // 데이터 셋 객체가 없으면 아무일도 하지 않는다.
            if (a_DataSet == null || GlobalVar.FutureMstDataDownloaded == false)
                return;

            m_ChartCtrl.Series["Put"].Points.Clear();
            m_ChartCtrl.Series["Call"].Points.Clear();
            m_ChartCtrl.Series["AvePut"].Points.Clear();
            m_ChartCtrl.Series["AveCall"].Points.Clear();
            CPSvrNew7221Table dataTable = a_DataSet.GetCPSvrNew7221Table();
            int rowCount = dataTable.GetRowCount();
            double buyValue = 0;
            double sellValue = 0;
            for (int i = 0; i < rowCount; i++)
            {
                DataRow row = dataTable.Rows[i];
                try
                {
                    // 값이 없을 경우는 넘어 간다.
                    if (row["개인옵션콜순매수"] == DBNull.Value)
                        continue;

                    buyValue = Convert.ToDouble(row["개인옵션콜순매수"]);
                    sellValue = Convert.ToDouble(row["개인옵션풋순매수"]);
                    m_ChartCtrl.Series["Call"].Points.AddXY(i, buyValue);
                    m_ChartCtrl.Series["Put"].Points.AddXY(i, sellValue);
                    m_ChartCtrl.Series["Call"].Points[i].XValue = i;
                    int hour = Convert.ToInt32(row["시각"]);
                    if (hour != 0)
                        m_ChartCtrl.Series["Call"].Points[i].AxisLabel = row["시각"].ToString();
                    else
                        m_ChartCtrl.Series["Call"].Points[i].AxisLabel = GlobalVar.HogaDayIndexToTime(i).ToString();

                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
            if (rowCount > a_AveRange + 1)
            {
                m_ChartCtrl.DataManipulator.FinancialFormula(FinancialFormula.ExponentialMovingAverage, a_AveRange.ToString(), "Call", "AveCall");
                m_ChartCtrl.DataManipulator.FinancialFormula(FinancialFormula.ExponentialMovingAverage, a_AveRange.ToString(), "Put", "AvePut");
            }
        }

        public void SetChartData(int a_CurIndex, EasyTrader.ETDataSet a_DataSet, int a_AveRange)
        {
            // 데이터 셋 객체가 없으면 아무일도 하지 않는다.
            if (a_DataSet == null)
                return;

            m_ChartCtrl.Series["Put"].Points.Clear();
            m_ChartCtrl.Series["Call"].Points.Clear();
            m_ChartCtrl.Series["AvePut"].Points.Clear();
            m_ChartCtrl.Series["AveCall"].Points.Clear();
            CPSvrNew7221Table dataTable = a_DataSet.GetCPSvrNew7221Table();
            int rowCount = dataTable.GetRowCount();
            if (rowCount == 0)
                return;
            if (rowCount - 1 < a_CurIndex)
                return;

            double buyValue = 0;
            double sellValue = 0;
            for (int i = 0; i <= a_CurIndex; i++)
            {
                DataRow row = dataTable.Rows[i];
                try
                {
                    // 값이 없을 경우는 넘어 간다.
                    if (row["개인옵션콜순매수"] == DBNull.Value)
                        continue;

                    buyValue = Convert.ToDouble(row["개인옵션콜순매수"]);
                    sellValue = Convert.ToDouble(row["개인옵션풋순매수"]);
                    m_ChartCtrl.Series["Call"].Points.AddXY(i, buyValue);
                    m_ChartCtrl.Series["Put"].Points.AddXY(i, sellValue);
                    m_ChartCtrl.Series["Call"].Points[i].XValue = i;
                    int hour = Convert.ToInt32(row["시각"]);
                    if (hour != 0)
                        m_ChartCtrl.Series["Call"].Points[i].AxisLabel = row["시각"].ToString();
                    else
                        m_ChartCtrl.Series["Call"].Points[i].AxisLabel = GlobalVar.HogaDayIndexToTime(i).ToString();

                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }

            if (a_CurIndex + 1 > a_AveRange + 1)
            {
                m_ChartCtrl.DataManipulator.FinancialFormula(FinancialFormula.ExponentialMovingAverage, a_AveRange.ToString(), "Call", "AveCall");
                m_ChartCtrl.DataManipulator.FinancialFormula(FinancialFormula.ExponentialMovingAverage, a_AveRange.ToString(), "Put", "AvePut");
            }

        }

        public double GetCallAveVal()
        {
            if (m_ChartCtrl == null)
                return -1.0;
            int pointCount = m_ChartCtrl.Series["AveCall"].Points.Count;
            if (pointCount < GlobalVar.HogaValRefRange)
                return -1.0;

            double curBuyAveVal = m_ChartCtrl.Series["AveCall"].Points[pointCount - 1].YValues[0];
            return curBuyAveVal;
        }

        public double GetCallAveVal(int a_CurIndex)
        {
            if (m_ChartCtrl == null)
                return -1.0;
            int pointCount = m_ChartCtrl.Series["AveCall"].Points.Count;
            if (pointCount < GlobalVar.HogaValRefRange)
                return -1.0;
            int curIndex = Math.Max(0, a_CurIndex);
            curIndex = Math.Min(curIndex, pointCount - 1);

            double curBuyAveVal = m_ChartCtrl.Series["AveCall"].Points[curIndex].YValues[0];
            return curBuyAveVal;
        }

        public double GetPutAveVal()
        {
            if (m_ChartCtrl == null)
                return -1.0;
            int pointCount = m_ChartCtrl.Series["AvePut"].Points.Count;
            if (pointCount < GlobalVar.HogaValRefRange)
                return -1.0;

            double curSellAveVal = m_ChartCtrl.Series["AvePut"].Points[pointCount - 1].YValues[0];
            return curSellAveVal;
        }

        public double GetPutAveVal(int a_CurIndex)
        {
            if (m_ChartCtrl == null)
                return -1.0;
            int pointCount = m_ChartCtrl.Series["AvePut"].Points.Count;
            if (pointCount < GlobalVar.HogaValRefRange)
                return -1.0;
            int curIndex = Math.Max(0, a_CurIndex);
            curIndex = Math.Min(curIndex, pointCount - 1);

            double curSellAveVal = m_ChartCtrl.Series["AvePut"].Points[curIndex].YValues[0];
            return curSellAveVal;
        }


        private EasyTrader.Wave.WaveManager m_CallWaveManager = new EasyTrader.Wave.WaveManager();
        public EasyTrader.Wave.WaveManager CallWaveManager
        {
            get { return m_CallWaveManager; }
            set { m_CallWaveManager = value; }
        }
        private EasyTrader.Wave.WaveManager m_PutWaveManager = new EasyTrader.Wave.WaveManager();
        public EasyTrader.Wave.WaveManager PutWaveManager
        {
            get { return m_PutWaveManager; }
            set { m_PutWaveManager = value; }
        }

        public void MakeWave(int a_CurIndex)
        {
            if (m_CallWaveManager != null)
            {
                m_CallWaveManager.EasyTraderDataSet = m_EasyTraderDataSet;
                m_CallWaveManager.MakeWaveListForCall(a_CurIndex + 1);
            }
            if (m_PutWaveManager != null)
            {
                m_PutWaveManager.EasyTraderDataSet = m_EasyTraderDataSet;
                m_PutWaveManager.MakeWaveListForPut(a_CurIndex + 1);
            }
        }

        private EasyTrader.Signal.ForecastingInfo m_ForeInfo = new EasyTrader.Signal.ForecastingInfo();

        public override int GetSignal(int a_DataCount)
        {
            int signalVal = GlobalVar.SignalNone;

            return signalVal;
        }

        // 이 함수는 개인콜풋의 시간 점유율을 계산한다.
        public int GetCallPutTimeOccupation(int a_CurIndex, ref int a_OccCall, ref int a_OccPut)
        {
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return 0;
            int rowCount = curTable.Rows.Count;
            if (a_CurIndex < 0)
                a_CurIndex = 0;
            if (a_CurIndex > rowCount - 1)
                a_CurIndex = rowCount - 1;
            int totalSquare = 0;
            if (rowCount == 0)
                return 0;
            a_OccCall = 0;
            a_OccPut = 0;
            for (int i = 0; i < a_CurIndex; i++)
            {
                DataRow row = curTable.Rows[i];
                if (row["개인옵션콜순매수"] == DBNull.Value)
                    return 0;
                int call = Convert.ToInt32(row["개인옵션콜순매수"]);
                int put = Convert.ToInt32(row["개인옵션풋순매수"]);
                if (call > put)
                    a_OccCall++;
                else if (put > call)
                    a_OccPut++;
            }

            return totalSquare;
        }

        public int GetCallDayHigh(int a_CurIndex)
        {
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return 0;
            int rowCount = curTable.Rows.Count;
            if (rowCount == 0)
                return 0;
            int curIndex = Math.Min(a_CurIndex, rowCount - 1);
            int maxBuy = -99999;
            for (int i = 0; i <= curIndex; i++)
            {
                DataRow row = curTable.Rows[i];
                if (row["개인옵션콜순매수"] == DBNull.Value)
                    return 0;
                int buy = Convert.ToInt32(row["개인옵션콜순매수"]);
                if (buy > maxBuy)
                {
                    maxBuy = buy;
                }
            }

            return maxBuy;
        }

        public int GetCallDayHigh(int a_CurIndex, ref int a_PutVal)
        {
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return 0;
            int rowCount = curTable.Rows.Count;
            if (rowCount == 0)
                return 0;
            int curIndex = Math.Min(a_CurIndex, rowCount - 1);
            int maxBuy = -99999;
            a_PutVal = 0;
            for (int i = 0; i <= curIndex; i++)
            {
                DataRow row = curTable.Rows[i];
                if (row["개인옵션콜순매수"] == DBNull.Value)
                    return 0;
                int buy = Convert.ToInt32(row["개인옵션콜순매수"]);
                int sell = Convert.ToInt32(row["개인옵션풋순매수"]);
                if (buy > maxBuy)
                {
                    maxBuy = buy;
                    a_PutVal = sell;
                }
            }

            return maxBuy;
        }

        public int GetPutDayHigh(int a_CurIndex)
        {
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return 0;
            int rowCount = curTable.Rows.Count;
            if (rowCount == 0)
                return 0;
            int curIndex = Math.Min(a_CurIndex, rowCount - 1);
            int maxSell = -99999;
            for (int i = 0; i <= curIndex; i++)
            {
                DataRow row = curTable.Rows[i];
                if (row["개인옵션풋순매수"] == DBNull.Value)
                    return 0;
                int sell = Convert.ToInt32(row["개인옵션풋순매수"]);
                if (sell > maxSell)
                {
                    maxSell = sell;
                }
            }

            return maxSell;
        }

        public int GetPutDayHigh(int a_CurIndex, ref int a_CallVal)
        {
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return 0;
            int rowCount = curTable.Rows.Count;
            if (rowCount == 0)
                return 0;
            int curIndex = Math.Min(a_CurIndex, rowCount - 1);
            int maxSell = -99999;
            a_CallVal = 0;
            for (int i = 0; i <= curIndex; i++)
            {
                DataRow row = curTable.Rows[i];
                if (row["개인옵션풋순매수"] == DBNull.Value)
                    return 0;
                int sell = Convert.ToInt32(row["개인옵션풋순매수"]);
                int buy = Convert.ToInt32(row["개인옵션콜순매수"]);
                if (sell > maxSell)
                {
                    maxSell = sell;
                    a_CallVal = buy;
                }
            }

            return maxSell;
        }

        // 전체 공간 점유율을 계산한다.
        public int GetTotalCallPutSquare2(int a_CurIndex, ref int a_CallSquare, ref int a_PutSquare, ref int a_TotalSquare)
        {
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return 0;
            int rowCount = curTable.Rows.Count;
            if (rowCount == 0)
                return 0;
            if (a_CurIndex < 0)
                a_CurIndex = 0;
            if (a_CurIndex > rowCount - 1)
                a_CurIndex = rowCount - 1;
            int totalSquare = 0;
            a_CallSquare = 0;
            a_PutSquare = 0;
            a_TotalSquare = 0;
            DataRow row = curTable.Rows[0];
            if (rowCount == 0)
                return 0;
            int firstCall = Convert.ToInt32(row["개인옵션콜순매수"]);
            int firstPut = Convert.ToInt32(row["개인옵션풋순매수"]);
            // 콜풋 중 작은 값으로 한다.
            int openVal = Math.Max(firstCall, firstPut);

            row = curTable.Rows[a_CurIndex];
            if (row["개인옵션콜순매수"] == DBNull.Value)
                return 0;
            for (int i = a_CurIndex; i >= 0; i--)
            {
                row = curTable.Rows[i];
                int call = Convert.ToInt32(row["개인옵션콜순매수"]) - openVal;
                int put = Convert.ToInt32(row["개인옵션풋순매수"]) - openVal;
                if (call > 0)
                    a_CallSquare += call;
                if (put > 0)
                    a_PutSquare += put;
                a_TotalSquare += Math.Max(call, put);
            }

            return totalSquare = a_TotalSquare;
        }

        public int GetTotalCallPutSquareOld(int a_CurIndex, ref int a_CallSquare, ref int a_PutSquare, ref int a_TotalSquare)
        {
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return 0;
            int rowCount = curTable.Rows.Count;
            if (rowCount == 0)
                return 0;
            if (a_CurIndex < 0)
                a_CurIndex = 0;
            if (a_CurIndex > rowCount - 1)
                a_CurIndex = rowCount - 1;
            int totalSquare = 0;
            a_CallSquare = 0;
            a_PutSquare = 0;
            a_TotalSquare = 0;
            DataRow row = curTable.Rows[0];
            if (rowCount == 0)
                return 0;
            int callMin = GetPersonCallMin(a_CurIndex);
            int putMin = GetPersonPutMin(a_CurIndex);
            // 콜풋 중 작은 값으로 한다.
            int openVal = Math.Min(callMin, putMin);

            row = curTable.Rows[a_CurIndex];
            if (row["개인옵션콜순매수"] == DBNull.Value)
                return 0;
            for (int i = a_CurIndex; i >= 0; i--)
            {
                row = curTable.Rows[i];
                int call = Convert.ToInt32(row["개인옵션콜순매수"]) - openVal;
                int put = Convert.ToInt32(row["개인옵션풋순매수"]) - openVal;
                if (call > 0)
                    a_CallSquare += call;
                if (put > 0)
                    a_PutSquare += put;
                a_TotalSquare += Math.Max(call, put);
            }

            return totalSquare = a_TotalSquare;
        }


        public int GetTotalCallPutSquare(int a_CurIndex, ref int a_CallSquare, ref int a_PutSquare, ref int a_TotalSquare)
        {
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return 0;
            int rowCount = curTable.Rows.Count;
            if (rowCount == 0)
                return 0;
            if (a_CurIndex < 0)
                a_CurIndex = 0;
            if (a_CurIndex > rowCount - 1)
                a_CurIndex = rowCount - 1;
            int totalSquare = 0;
            a_CallSquare = 0;
            a_PutSquare = 0;
            a_TotalSquare = 0;
            DataRow row = curTable.Rows[0];
            if (rowCount == 0)
                return 0;
            int callMin = GetPersonCallMin(a_CurIndex);
            int putMin = GetPersonPutMin(a_CurIndex);
            // 콜풋 중 작은 값으로 한다.
            int openVal = Math.Min(callMin, putMin);

            row = curTable.Rows[a_CurIndex];
            if (row["개인옵션콜순매수"] == DBNull.Value)
                return 0;
            for (int i = a_CurIndex; i >= 0; i--)
            {
                row = curTable.Rows[i];
                int call = Convert.ToInt32(row["개인옵션콜순매수"]);
                int put = Convert.ToInt32(row["개인옵션풋순매수"]);
                a_CallSquare += call;
                a_PutSquare += put;
                    
                a_TotalSquare += Math.Max(call, put);
            }

            return totalSquare = a_TotalSquare;
        }


        private int GetPersonCallMin(int a_CurIndex)
        {
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return 0;
            int rowCount = curTable.Rows.Count;
            if (rowCount == 0)
                return 0;
            if (a_CurIndex < 0)
                a_CurIndex = 0;
            if (a_CurIndex > rowCount - 1)
                a_CurIndex = rowCount - 1;
            int min = 999999999;
            for (int i = 0; i <= a_CurIndex; i++)
            {
                DataRow row = curTable.Rows[i];
                int call = Convert.ToInt32(row["개인옵션콜순매수"]);
                if (call < min)
                    min = call;
            }

            return min;
        }

        private int GetPersonPutMin(int a_CurIndex)
        {
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return 0;
            int rowCount = curTable.Rows.Count;
            if (rowCount == 0)
                return 0;
            if (a_CurIndex < 0)
                a_CurIndex = 0;
            if (a_CurIndex > rowCount - 1)
                a_CurIndex = rowCount - 1;
            int min = 999999999;
            for (int i = 0; i <= a_CurIndex; i++)
            {
                DataRow row = curTable.Rows[i];
                int put = Convert.ToInt32(row["개인옵션풋순매수"]);
                if (put < min)
                    min = put;
            }

            return min;
        }

        public EasyTrader.Wave.PriceWave FindCallWave(int a_Index)
        {
            PriceWaveList waveList = m_CallWaveManager.ArragedWaveList;
            if (waveList.Count == 0)
                return null;

            for (int i = 0; i < waveList.Count; i++)
            {
                EasyTrader.Wave.PriceWave wave = waveList[i];
                if (wave.StartX <= a_Index && a_Index <= wave.EndX)
                    return wave;
            }

            return null;
        }

        public EasyTrader.Wave.PriceWave FindPutWave(int a_Index)
        {
            PriceWaveList waveList = m_PutWaveManager.ArragedWaveList;
            if (waveList.Count == 0)
                return null;

            for (int i = 0; i < waveList.Count; i++)
            {
                EasyTrader.Wave.PriceWave wave = waveList[i];
                if (wave.StartX <= a_Index && a_Index <= wave.EndX)
                    return wave;
            }

            return null;
        }

        // 이 함수는 파동의 고점저점을 구한다. 이때 고가와 저가, 종가에 대하여 각각 구한다.
        public void FindCallWaveHighLow(EasyTrader.Wave.PriceWave a_Wave)
        {
            if (a_Wave == null || m_EasyTraderDataSet == null)
                return;

            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return;

            int startX = a_Wave.StartX - GlobalVar.ForecastCompLen;
            startX = Math.Max(0, startX);
            int endX = Math.Min(a_Wave.EndX, curTable.GetRowCount() - 1);
            DataRow row = curTable.Rows[startX];
            int high = -1000000;
            int low = 1000000;
            for (int j = startX; j <= endX; j++)
            {
                row = curTable.Rows[j];
                int val = Convert.ToInt32(row["개인옵션콜순매수"]);
                if (val != 0 && val > high)
                {
                    high = val;
                    a_Wave.HighX = j;
                    a_Wave.HighY = high;
                }
                if (val != 0 && val < low)
                {
                    low = val;
                    a_Wave.LowX = j;
                    a_Wave.LowY = low;
                }
            }
        }


        // 이 함수는 파동의 고점저점을 구한다. 이때 고가와 저가, 종가에 대하여 각각 구한다.
        public void FindPutWaveHighLow(EasyTrader.Wave.PriceWave a_Wave)
        {
            if (a_Wave == null || m_EasyTraderDataSet == null)
                return;

            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return;

            int startX = a_Wave.StartX - GlobalVar.ForecastCompLen;
            startX = Math.Max(0, startX);
            int endX = Math.Min(a_Wave.EndX, curTable.GetRowCount() - 1);
            DataRow row = curTable.Rows[startX];
            int high = -1000000;
            int low = 1000000;
            for (int j = startX; j <= endX; j++)
            {
                row = curTable.Rows[j];
                int val = Convert.ToInt32(row["개인옵션풋순매수"]);
                if (val != 0 && val > high)
                {
                    high = val;
                    a_Wave.HighX = j;
                    a_Wave.HighY = high;
                }
                if (val != 0 && val < low)
                {
                    low = val;
                    a_Wave.LowX = j;
                    a_Wave.LowY = low;
                }
            }
        }


        public void FindPutWaveAveHighLow(EasyTrader.Wave.PriceWave a_Wave, ref double a_Max, ref double a_Min)
        {
            if (a_Wave == null || m_EasyTraderDataSet == null)
                return;

            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return;

            int startX = a_Wave.StartX;
            startX = Math.Max(3, startX);
            if (startX > curTable.GetRowCount() - 1)
                return;

            int endX = Math.Min(a_Wave.EndX, curTable.GetRowCount() - 1);
            a_Min = GetPutAveVal(startX);
            a_Max = a_Min;
            for (int j = startX; j <= endX; j++)
            {
                double sell = GetPutAveVal(j);
                if (sell > a_Max)
                    a_Max = sell;
                if (sell < a_Min)
                    a_Min = sell;
            }
        }

        public void FindCallWaveAveHighLow(EasyTrader.Wave.PriceWave a_Wave, ref double a_Max, ref double a_Min)
        {
            if (a_Wave == null || m_EasyTraderDataSet == null)
                return;

            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return;

            int startX = a_Wave.StartX;
            startX = Math.Max(3, startX);
            if (startX > curTable.GetRowCount() - 1)
                return;

            int endX = Math.Min(a_Wave.EndX, curTable.GetRowCount() - 1);
            a_Min = GetCallAveVal(startX);
            a_Max = a_Min;
            for (int j = startX; j <= endX; j++)
            {
                double sell = GetCallAveVal(j);
                if (sell > a_Max)
                    a_Max = sell;
                if (sell < a_Min)
                    a_Min = sell;
            }
        }

        // 풋을 우선순위로 해서 풋이 위에 있을 때는 매수로 콜이 위에 있을 때는 매도로 대응한다.
        public double GetPersonPutCallSignal(int a_CurIndex)
        {
            double signalVal = GlobalVar.SignalNone;
            double curSignal = FindOptionPersonInvDivType(a_CurIndex, GlobalVar.RegressionType, GlobalVar.ReferenceRange);
            if (curSignal == 0)
                return signalVal;

            signalVal = ((9.0 - (Math.Abs(curSignal) - 1.0)) / 9.0) * 100.0;
            return curSignal > 0.0 ? signalVal : -signalVal;
        }

        // 외국인과 개인의 코스피 현황을 보고 신호를 결정한다.
        // 외국인이 위에 있을 때는 매수를 밑에 있을 때는 매도로 대응한다.
        public double GetForeignPersonKospiSignal(ForecastingInfo a_ForeignInfo, int a_CurIndex)
        {
            double signalVal = GlobalVar.SignalNone;
            if (a_ForeignInfo == null)
                return signalVal;
            double curSignal = FindKospiForeignPersonInvDivType(a_CurIndex, GlobalVar.RegressionType, GlobalVar.ReferenceRange);
            if (curSignal == 0)
                return signalVal;

            double deltaY = a_ForeignInfo.EndY - a_ForeignInfo.StartY;

            return FindInvDivPercent(deltaY, curSignal);
        }

        // 기관과 개인의 코스피 현황을 보고 신호를 결정한다.
        // 기관이 위에 있을 때는 매수를 밑에 있을 때는 매도로 대응한다.
        public double GetOrganPersonKospiSignal(ForecastingInfo a_OrganInfo, int a_CurIndex)
        {
            double signalVal = GlobalVar.SignalNone;
            if (a_OrganInfo == null)
                return signalVal;
            double curSignal = FindKospiOrganPersonInvDivType(a_CurIndex, GlobalVar.RegressionType, GlobalVar.ReferenceRange);
            if (curSignal == 0)
                return signalVal;

            double deltaY = a_OrganInfo.EndY - a_OrganInfo.StartY;
            
            return FindInvDivPercent(deltaY, curSignal);
        }

        // 이 함수는 외국인 선물지수에 의해서 매도와 매수를 결정해 반환한다.
        // 퍼센트로 반환을 한다.
        public double GetForeighFutureSignal(ForecastingInfo a_ForeignInfo, int a_CurIndex)
        {
            double signalVal = GlobalVar.SignalNone;
            if (a_ForeignInfo == null)
                return signalVal;
            double curSignal = FindKospiPersonFutureForeignInvDivType(a_CurIndex, GlobalVar.RegressionType, GlobalVar.ReferenceRange);
            if (curSignal == 0)
                return signalVal;

            double deltaY = a_ForeignInfo.EndY - a_ForeignInfo.StartY;

            return FindInvDivPercent(deltaY, curSignal);
        }

        public int FindKospiProgramPersonInvDivType(int a_CurIndex, string a_RegType, int a_MaxRange)
        {
            int invdiv = 0;
            ForecastingInfo programForecast = GetProgramForecastingInfo("전체순매수금액", GlobalVar.RegressionType, a_CurIndex, GlobalVar.ReferenceRange);
            ForecastingInfo personForecast = GetSubjectForecastingInfo("코스피개인순매수", a_RegType, a_CurIndex, a_MaxRange);
            if (programForecast == null || personForecast == null)
                return invdiv;

            invdiv = SignalManager.FindInvDivType(programForecast, personForecast);

            return invdiv;
        }

        public int FindKospiPersonFutureForeignInvDivType(int a_CurIndex, string a_RegType, int a_MaxRange)
        {
            int invdiv = 0;
            ForecastingInfo foreignForecast = GetSubjectForecastingInfo("선물외국인순매수", GlobalVar.RegressionType, a_CurIndex, GlobalVar.ReferenceRange);
            ForecastingInfo personForecast = GetSubjectForecastingInfo("코스피개인순매수", a_RegType, a_CurIndex, a_MaxRange);
            if (foreignForecast == null || personForecast == null)
                return invdiv;
            invdiv = SignalManager.FindInvDivType(foreignForecast, personForecast);
            return invdiv;
        }

        // 이 함수는 외국인 선물지수에 의해서 매도와 매수를 결정해 반환한다.
        // 퍼센트로 반환을 한다.
        public double GetProgramSignal(ForecastingInfo a_ProgramInfo, int a_CurIndex)
        {
            double signalVal = GlobalVar.SignalNone;
            if (a_ProgramInfo == null)
                return signalVal;
            double curSignal = FindKospiProgramPersonInvDivType(a_CurIndex, GlobalVar.RegressionType, GlobalVar.ReferenceRange);
            if (curSignal == 0)
                return signalVal;
            double deltaY = a_ProgramInfo.EndY - a_ProgramInfo.StartY;

            return FindInvDivPercent(deltaY, curSignal);
        }

        public double GetHigherOptionVal()
        {
            EasyTrader.CPSvrNew7221Table curTable = m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return 0;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0)
                return 0;
            DataRow row = curTable.Rows[rowCount - 1];
            double callVal = Convert.ToDouble(row["개인옵션콜순매수"]);
            double putVal = Convert.ToDouble(row["개인옵션풋순매수"]);
            return Math.Max(callVal, putVal);
        }

        public double GetHigherOptionVal(int a_CurIndex)
        {
            EasyTrader.CPSvrNew7221Table curTable = m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return 0;
            int rowCount = curTable.GetRowCount();
            if (rowCount == 0 || a_CurIndex < 0 || a_CurIndex >= rowCount)
                return 0;
            DataRow row = curTable.Rows[a_CurIndex];
            double callVal = Convert.ToDouble(row["개인옵션콜순매수"]);
            double putVal = Convert.ToDouble(row["개인옵션풋순매수"]);
            return Math.Max(callVal, putVal);
        }

        public ForecastingInfo GetProgramForecastingInfo(string a_ColName, string a_RegType, int a_MaxRange)
        {
            if (a_ColName == "")
                return null;
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvr8111STable();
            return Forecaster.GetForecastingInfo(curTable, a_ColName, a_RegType, a_MaxRange);
        }

        public ForecastingInfo GetProgramForecastingInfo(string a_ColName, string a_RegType, int a_DayIndex, int a_MaxRange)
        {
            if (a_ColName == "")
                return null;
            EasyTrader.CPSvr8111STable curTable = m_EasyTraderDataSet.GetCPSvr8111STable();
            if (curTable == null)
                return null;
            if (curTable.GetRowCount() == 0)
                return null;

            return Forecaster.GetForecastingInfo(curTable, a_ColName, a_RegType, a_DayIndex, a_MaxRange, true);
        }

        public int GetProgramForecastingInfo(ForecastingInfo a_Fore, string a_ColName, string a_RegType, int a_DayIndex, int a_MaxRange)
        {
            if (a_ColName == "")
                return -1;
            EasyTrader.CPSvr8111STable curTable = m_EasyTraderDataSet.GetCPSvr8111STable();
            if (curTable == null)
                return -1;
            if (curTable.GetRowCount() == 0)
                return -1;

            return Forecaster.GetForecastingInfo(a_Fore, curTable, a_ColName, a_RegType, a_DayIndex, a_MaxRange, true);
        }

        public ForecastingInfo GetSubjectForecastingInfo(string a_ColName, string a_RegType, int a_DayIndex, int a_MaxRange)
        {
            if (a_ColName == "")
                return null;
            EasyTrader.CPSvrNew7221Table curTable = m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return null;
            if (curTable.GetRowCount() == 0)
                return null;

            return Forecaster.GetForecastingInfo(curTable, a_ColName, a_RegType, a_DayIndex, a_MaxRange, true);
        }

        public int GetSubjectForecastingInfo(ForecastingInfo a_Fore, string a_ColName, string a_RegType, int a_DayIndex, int a_MaxRange)
        {
            if (a_ColName == "" || a_Fore == null)
                return -1;
            EasyTrader.CPSvrNew7221Table curTable = m_EasyTraderDataSet.GetCPSvrNew7221Table();
            if (curTable == null)
                return -1;
            if (curTable.GetRowCount() == 0)
                return -1;

            return Forecaster.GetForecastingInfo(a_Fore, curTable, a_ColName, a_RegType, a_DayIndex, a_MaxRange, true);
        }

        public ForecastingInfo GetSubjectForecastingInfo(string a_ColName, string a_RegType, int a_MaxRange)
        {
            if (a_ColName == "")
                return null;
            EasyTrader.DataSet.ETDataTable curTable = (EasyTrader.DataSet.ETDataTable)m_EasyTraderDataSet.GetCPSvrNew7221Table();
            return Forecaster.GetForecastingInfo(curTable, a_ColName, a_RegType, a_MaxRange);
        }

        public int FindKospiForeignPersonInvDivType(string a_RegType, int a_MaxRange)
        {
            int invdiv = 0;
            ForecastingInfo foreignForecast = GetSubjectForecastingInfo("코스피외국인순매수", a_RegType, a_MaxRange);
            ForecastingInfo personForecast = GetSubjectForecastingInfo("코스피개인순매수", a_RegType, a_MaxRange);
            if (foreignForecast == null || personForecast == null)
                return invdiv;
            invdiv = SignalManager.FindInvDivType(foreignForecast, personForecast);
            return invdiv;
        }

        public int FindKospiForeignPersonInvDivType(int a_CurIndex, string a_RegType, int a_MaxRange)
        {
            int invdiv = 0;
            ForecastingInfo foreignForecast = GetSubjectForecastingInfo("코스피외국인순매수", a_RegType, a_CurIndex, a_MaxRange);
            ForecastingInfo personForecast = GetSubjectForecastingInfo("코스피개인순매수", a_RegType, a_CurIndex, a_MaxRange);
            if (foreignForecast == null || personForecast == null)
                return invdiv;
            
            invdiv = SignalManager.FindInvDivType(foreignForecast, personForecast);
            return invdiv;
        }

        public int FindKospiOrganPersonInvDivType(string a_RegType, int a_MaxRange)
        {
            int invdiv = 0;
            ForecastingInfo organForecast = GetSubjectForecastingInfo("코스피기관계순매수", a_RegType, a_MaxRange);
            ForecastingInfo personForecast = GetSubjectForecastingInfo("코스피개인순매수", a_RegType, a_MaxRange);
            if (organForecast == null || personForecast == null)
                return invdiv;

            invdiv = SignalManager.FindInvDivType(organForecast, personForecast);
            return invdiv;
        }

        public int FindKospiOrganPersonInvDivType(int a_CurIndex, string a_RegType, int a_MaxRange)
        {
            int invdiv = 0;
            ForecastingInfo organForecast = GetSubjectForecastingInfo("코스피기관계순매수", a_RegType, a_CurIndex, a_MaxRange);
            ForecastingInfo personForecast = GetSubjectForecastingInfo("코스피개인순매수", a_RegType, a_CurIndex, a_MaxRange);
            
            if (organForecast == null || personForecast == null)
                return invdiv;
            invdiv = SignalManager.FindInvDivType(organForecast, personForecast);
            return invdiv;
        }

        public int FindOptionPersonInvDivType(string a_RegType, int a_MaxRange)
        {
            int invdiv = 0;
            ForecastingInfo putForecast = GetSubjectForecastingInfo("개인옵션풋순매수", a_RegType, a_MaxRange);
            ForecastingInfo callForecast = GetSubjectForecastingInfo("개인옵션콜순매수", a_RegType, a_MaxRange);
            if (putForecast == null || callForecast == null)
                return invdiv;
            return SignalManager.FindInvDivType(putForecast, callForecast);
        }

        // 풋이 우선순위로 파악이 된다. - 개인과는 반대방향을 찾기 위해서 이렇게 한다.
        public int FindOptionPersonInvDivType(int a_CurIndex, string a_RegType, int a_MaxRange)
        {
            int invdiv = 0;
            ForecastingInfo putForecast = GetSubjectForecastingInfo("개인옵션풋순매수", a_RegType, a_CurIndex, a_MaxRange);
            ForecastingInfo callForecast = GetSubjectForecastingInfo("개인옵션콜순매수", a_RegType, a_CurIndex, a_MaxRange);
            if (putForecast == null || callForecast == null)
                return invdiv;
            invdiv = SignalManager.FindInvDivType(putForecast, callForecast);

            m_CallPutInvDiv = invdiv;

            return invdiv;
        }
    }
}
